﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Neoit.Utils.Extensions
{
    /// <summary>
    /// 实体扩展
    /// </summary>
    public static class EntityExtension
    {
        #region 对实体各属性执行Func()

        /// <summary>
        /// 对象中的string属性值执行Trim()
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        public static void TrimForString<T>(this T t) where T : new()
        {
            t.ForeachString(s => s.Has() ? s.Trim() : s);
        }
        /// <summary>
        /// 对实体各string属性执行Func
        /// </summary>
        public static void ForeachString<T>(this T t, Func<string, string> func) where T : new()
        {
            t.Foreach(func);
        }
        /// <summary>
        /// 对实体各属性执行Func
        /// </summary>
        public static void Foreach<T, T2>(this T t, Func<T2, T2> func) where T : new()
        {
            if (t == null) return;
            foreach (var pi in t.GetType().GetProperties().Where(s => s.PropertyType.Equals(typeof(T2))))
            {
                if (pi.CanWrite) pi.SetValue(t, func((T2)pi.GetValue(t)));
            }
        }
        #endregion

        #region 对象转Dictionary<string, object>
        /// <summary>
        /// 对象转Dictionary&lt;string,object>
        /// </summary>
        public static Dictionary<string, object> ToDic<T>(this T t) where T : new()
        {
            var dic = new Dictionary<string, object> { };
            if (t != null)
            {
                foreach (var pi in t.GetType().GetProperties()) dic.Add(pi.Name, pi.GetValue(t));
                return dic;
            }
            return dic;
        }
        /// <summary>
        /// Dictionary&lt;string,object>转对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static T ToEntity<T>(this Dictionary<string, object> dictionary) where T: new()
        {
            if (dictionary == null || dictionary.Count == 0) return default;
            T entity = new T();
            foreach (var prop in entity.GetType().GetProperties())
            {
                if (dictionary.ContainsKey(prop.Name))
                {
                    prop.SetValue(entity, Convert.ChangeType(dictionary[prop.Name], prop.PropertyType));
                }
            }
            return entity;
        }
        /// <summary>
        /// 静态类转Dictionary&lt;string,object>
        /// </summary>
        public static Dictionary<string, object> ToDicForStaticClass(this Type t)
        {
            var dic = new Dictionary<string, object> { };
            foreach (var pi in t.GetProperties()) dic.Add(pi.Name, pi.GetValue(null));
            return dic;
        }
        #endregion

        #region 对象EqualsX
        /// <summary>
        /// 对象转Dictionary&lt;string,object>
        /// </summary>
        public static bool EqualsX<T, T2>(this T t1, T2 t2, params Expression<Func<T, object>>[] predicates) where T : new()
        {
            if (t1 == null && t2 == null) return true;
            if (t1 == null || t2 == null) return false;
            if (predicates.Length == 0) return string.Equals(JsonConvert.SerializeObject(t1), JsonConvert.SerializeObject(t2));
            foreach (var item in predicates)
            {
                var memberExpression = item.Body as MemberExpression;
                string propertyName = memberExpression.Member.Name;

                PropertyInfo prop = typeof(T).GetProperty(propertyName);
                var v1 = prop.GetValue(t1);

                PropertyInfo prop2 = typeof(T2).GetProperty(propertyName);
                if (prop2 == null || (prop2 != null && !Equals(v1, prop2.GetValue(t2))))
                {
                    return false;
                }
            }
            return true;
        }
        #endregion

        //#region 对象转Dictionary<string, object>
        ///// <summary>
        ///// 对象转Dictionary&lt;string,object>
        ///// </summary>
        //public static Dictionary<string, object> Keys<T>(this T t) where T : new()
        //{
        //    var dic = new Dictionary<string, object> { };
        //    if (t != null)
        //    {
        //        foreach (var pi in t.GetType().GetProperties()) dic.Add(pi.Name, pi.GetValue(t));
        //        return dic;
        //    }
        //    return dic;
        //}
        //#endregion

        #region 深copy:Json序列化方式
        /// <summary>
        /// 深copy:Json序列化方式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static T DeepCopy<T>(this T t) where T : new()
        {
            var res = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(t));
            return res;
        }
        #endregion

        #region 获取字段信息的displayName
        /// <summary>
        /// 获取字段信息的displayName
        /// </summary>
        public static string GetDisplayName(this FieldInfo fieldInfo)
        {
            var displayAttribute = fieldInfo.GetCustomAttribute<DisplayAttribute>();
            if (displayAttribute != null)
            {
                return displayAttribute.Name;
            }
            else
            {
                var descriptionAttribute = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
                return descriptionAttribute?.Description ?? fieldInfo.Name;
            }
        }
        #endregion
    }

}
